﻿using DBUtility;
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WinServer;

namespace WinServer
{
    public class FileRecordProcessor
    {
        string filePath = $"{System.DateTime.Now.ToString("MMdd")}-Record.dat";
        /// <summary>
        /// main processer method 
        /// need override
        /// need no Exception throw out
        /// </summary>
        /// <param name="obj">对象</param>
        public void Process(object obj)
        {
            try
            {
                if (System.Configuration.ConfigurationManager.AppSettings["DataBaseEnabled"] == "1")
                {
                    byte[] byteData = obj as byte[];
                    using (FileStream fileStream = new FileStream(filePath, FileMode.Append))
                    {
                        fileStream.Write(byteData, 0, byteData.Length);
                    }
                }
            }
            catch (Exception EX)
            {
            }
        }
        public virtual void Process1(object obj)
        {
        }
        /// <summary>
        /// Catch publisher exception will call the method
        /// override the method  and write log to log file
        /// </summary>
        /// <param name="log">日志</param>
        public virtual void LogNotified(string log)
        {
            ////need override to write log to file
        }
        #region constructor
        /// <summary>
        /// 独立单线程处理类
        /// </summary>
        /// <param name="procesorName">处理器名称</param>
        public FileRecordProcessor(string procesorName, int mThreadCount)
        {
            threadName = System.Guid.NewGuid().ToString();
            this.mThreadCount = mThreadCount;
            Open();
        }
        #endregion
        #region "公共函数"       
        /// <summary>
        /// 关闭
        /// </summary>
        public void Close()
        {
            // 关闭数据处理线程
            try
            {
                if (_eventSemaphore != null)
                {
                    _messages.Clear();
                    _eventSemaphore.Release();
                    _handleThread.Join(100);
                    _handleThread.Abort();
                    // 关闭信号量
                    _eventSemaphore.Close();
                }
            }
            catch (Exception /*ex*/)
            {
            }
            finally
            {
                _eventSemaphore = null;
            }
        }
        /// <summary>
        /// 添加需要处理的obj
        /// </summary>
        /// <param name="obj">对象</param>
        public void AddProcessObj(object obj)
        {
            try
            {
                Monitor.Enter(_msgQueueSyncLock);
                if (_messages != null)
                {
                    _messages.Enqueue(obj);
                }
                if (_eventSemaphore != null)
                {
                    _eventSemaphore.Release();
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                Monitor.Exit(_msgQueueSyncLock);
            }
        }
        /// <summary>
        /// 开始进行处理
        /// </summary>
        public void Open()
        {
            if (this._handleThread == null || (!this._handleThread.IsAlive))
            {
                _eventSemaphore = new Semaphore(0, int.MaxValue);
                _handleThread = new Thread(new ThreadStart(BusinessDataHandleThreadEntry));
                _handleThread.SetApartmentState(ApartmentState.STA);
                _handleThread.Start();
            }
        }
        #endregion
        #region "私有函数"
        /// <summary>
        /// 添加到队列对象
        /// </summary>
        /// <param name="args">对象</param>
        private void AddobjToQueue(object args)
        {
            try
            {
                Monitor.Enter(_msgQueueSyncLock);
                _messages.Enqueue(args);
            }
            catch (Exception /*ex*/)
            {
            }
            finally
            {
                Monitor.Exit(_msgQueueSyncLock);
            }
        }
        /// <summary>
        /// 队列中
        /// </summary>
        /// <returns>对象</returns>
        private object DqueueArgs()
        {
            object args = null;
            try
            {
                Monitor.Enter(_msgQueueSyncLock);
                args = _messages.Dequeue();
            }
            catch (Exception /*ex*/)
            {
            }
            finally
            {
                Monitor.Exit(_msgQueueSyncLock);
            }
            return args;
        }
        #endregion
        #region field
        /// <summary>
        /// 事件队列
        /// </summary>
        private Queue<object> _messages = new Queue<object>();
        /// <summary>
        /// 事件处理线程
        /// </summary>
        private Thread _handleThread = null;
        /// <summary>
        /// 信号量
        /// </summary>
        private Semaphore _eventSemaphore = null;
        /// <summary>
        /// 消息队列同步锁
        /// </summary>
        private object _msgQueueSyncLock = new object();
        /// <summary>
        /// 线程的名字
        /// </summary>
        private string threadName = "Unknown";
        /// <summary>
        /// 消费线程数量
        /// </summary>
        private int mThreadCount = 1;
        #endregion
        /// <summary>
        /// 业务数据处理线程
        /// </summary>
        private void BusinessDataHandleThreadEntry()
        {
            //while (_eventSemaphore.WaitOne())
            while (true)
            {
                if (_messages.Count > 0)
                {
                    object args = DqueueArgs();
                    try
                    {
                        Process(args);
                    }
                    catch (Exception ex)
                    {
                    }
                }
                else
                {
                    Thread.Sleep(100);
                }
            }
        }
        public bool IsEmpty()
        {
            if (_messages.Count == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}